local ffi = require('ffi')
local struct = require('struct')

require('cdef.base')

local LICH = ffi.load('lich4s')

ffi.cdef[[

int cluster_is_solomode();

int nodetable_count(int *count);

int cluster_countnode(int *count);
int cluster_countnode_writeable(int *count);

int dispatch_list_storage_area(char *buf, int *count);

// inline uint64_t size2chknum(uint64_t);

int md_chunk_getid(const char *path, chkid_t *_chkid);

int stor_stat(const chkid_t *id, char *buf, int verbose);

struct dirent {
        unsigned long int d_ino;
        long int d_off;
        unsigned short int d_reclen;
        unsigned char d_type;
        char d_name[256];
};

]]

function print_obj(o)
        for k, v in pairs(o) do
                print(k, v)
        end
end


print(LICH)

function nodetable_count()
	local n = ffi.new('int[1]', 0)
        print(n)
	LICH.nodetable_count(n)
        print(n[0])
end

function cluster_countnode()
	local n = ffi.new('int[1]', 0)
        print(n)
	local ret = LICH.cluster_countnode(n)
        return {ret, n[0]}
end


function unpack_str(s)
        -- print s
        -- local n = struct.unpack('i4', s)
        -- local si = struct.unpack('s', s, 5)
        -- print(n, si, si:len())
        -- return si
        return struct.unpack('i4c0', s)
end

function dispatch_list_storage_area()
	local buf = ffi.new('char[4096]')
	local len = ffi.new('int[1]', 4096)
	local ret = LICH.dispatch_list_storage_area(buf, len)
	print('--buffer')
	print(len[0])
	print(buf)
        for i=0, len[0] - 1 do
                print(buf[i])
        end
        print(ffi.string(buf+4))

        local left = len[0]
        local count = 1
        local n
        local t = {}
        local s
        local si

        s = ffi.string(buf, left)
        while string.len(s) > 0 do
                print ('s=', s, s:len())
                si = unpack_str(s)
                print ('si=', si, 'len=', 4 + si:len())
                s = s:sub(4 + si:len() + 1)

                -- si = struct.unpack('i4s', s)
                -- n = si:len()
                -- n = 8
                -- print('s=', s, 'si=', si, 'n=', n)
                --
                -- print ('si=', si, type(si))

                -- s = s:sub(4 + n)
                -- TODO little/big
                -- n = buf[0]
                -- t[count] = ffi.string(buf+4, n-1)
                -- count = count + 1
                -- buf = buf + (4 + n)
                -- left = left - (4 + n)
        end
        --for k, v in pairs(t) do
        --        print (k, v)
        --end
        --return t
end

function size2chknum()
        print(LICH.size2chknum(10))
end

function md_chunk_getid()
        local chkid = ffi.new('chkid_t')
        print(LICH.md_chunk_getid('/iscsi', chkid))
        print(chkid)
        print(chkid.id, chkid.idx, chkid.type)

        local buf = ffi.new('char[4096]')
        print(LICH.stor_stat(chkid, buf, 1))
        print('buf', ffi.string(buf))
end

function listnode()
        local _uuid = ffi.new('uuid_t')
        local uuid = ffi.new('char[256]', 0)
        local buf = ffi.new('char[4096]', 0)
        local buflen = ffi.new('int[1]', 4096)
        local ptr = ffi.new('struct dirent *')

        LICH.uuid_generate(_uuid)
        LICH.uuid_unparse(_uuid, uuid)

        print(ffi.string(uuid))

        print(LICH.cluster_listnode_open(uuid))
        print('buflen=', buflen[0])
        print(LICH.cluster_listnode(buf, buflen, uuid, 0))

        local s = ffi.string(buf, buflen[0])
        print('len', s:len())
        print('buflen=', buflen[0])

	--
	-- cast
	local _ino = ffi.cast('unsigned long int', buf[0])
	local _off = ffi.cast('long int', buf[8])
	local _reclen = ffi.cast('unsigned short int', buf[17])
	local _type = ffi.cast('unsigned char', buf[18])
	local _name = ffi.cast('char *', buf[19])

	print('cast', _ino, _off, tonumber(_reclen), _type, _name)

	-- struct

        local d_ino, d_off, d_reclen, d_type, start
        local name
        local offset = 1
        local start = offset
	t = {}
        while offset < buflen[0] do
                print('---------------')
                print ('start=', start, offset)
                print('unpack', struct.unpack('LlHB', s, start))
                d_ino, d_off, d_reclen, d_type, start = struct.unpack('LlHB', s, start)
                name, start = struct.unpack('s', s, start)
                print('name=', name)

                if name:len() == 0 then
                        break
                end
                offset = offset + d_reclen
	        start = offset
		table.insert(t, name)
        end
	for k, v in pairs(t) do
		print('node', k, v)
	end
end

print(init_lich())

print(LICH.cluster_is_solomode())
print(nodetable_count())
print_obj(cluster_countnode())

dispatch_list_storage_area()

md_chunk_getid()

listnode()
